package cn.zhiquxing.service;

import cn.zhiquxing.dao.UserDao;
import cn.zhiquxing.mapper.UserMapper;
import cn.zhiquxing.pojo.User;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.aspectj.weaver.ast.Var;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Service
public class UserServiceImpl implements UserService, ApplicationContextAware {
    
    //1.解决自调用问题，@Transactional失效场景，实现ApplicationContext
    private ApplicationContext applicationContext;
    
    @Autowired
    public UserDao userDao;
    
    @Autowired
    private MongoTemplate mongoTemplate;
    
    @Override
    @Cacheable(value = "redisCache", key = "'redis_user_'+#id")
    public User getUser(Long id) {
        return userDao.getUser(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public int insertUser(User user) {
        return userDao.insertUser(user) ;
    }

    @Override
    @Transactional
    public int insertUsers(List<User> users) {
        int count = 0;
        //UserService bean = applicationContext.getBean(UserService.class);
        //2.使用AopContex.currentProxy()获取当前类的代理对象，同时在启动类增加 @EnableAspectJAutoProxy(exposeProxy = true)
        UserService bean = (UserService) AopContext.currentProxy();
        for (User user : users) {
            count += bean.insertUser(user);
        }
        return count;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    @CachePut(value = "redisCache", key = "'redis_user_'+#result.id")
    public User insertUser2(User user) {
        userDao.insertUser(user);
        return user;
    }


    @Override
    //更新数据库后，更新缓存
    @Transactional
    @CacheEvict(value = "redisCache", key = "'redis_user_'+#id")
    public int deleteUser(Long id) {
        return userDao.deleteUser(id);
    }

    @Override
    public List<User> findUsers(String userName, String note) {
        return userDao.findUsers(userName, note);
    }

    @Override
    @CachePut(value = "redisCache", condition = "#result != 'null'", key = "'redis_user_'+#id")
    @Transactional
    public User updateUser(Long id, String userName) {
        User user = this.getUser(id);
        if (Objects.isNull(user)) {
            return null;
        }
        user.setUserName(userName);
        userDao.updateUser(user);
        return user;
    }

    @Override
    public void saveUser(User user) {
        mongoTemplate.save(user);
    }

    @Override
    public User findUserById(Long id) {
        return mongoTemplate.findById(id, User.class);
    }

    @Override
    public List<User> findUser(String userName, String note, int skip, int limit) {
        // 用户名和备注设置为模糊查询准则
        Criteria criteria = Criteria.where("userName").regex(userName).and("note").regex(note);
        Query query = Query.query(criteria).limit(limit).skip(skip);
        return mongoTemplate.find(query, User.class);
    }

    @Override
    public DeleteResult deleteUserById(Long id) {
        // 构建条件
        Criteria criteria = Criteria.where("id").is(id);
        // 查询对象
        Query query = Query.query(criteria);
        DeleteResult remove = mongoTemplate.remove(query, User.class);
        return remove;
    }

    @Override
    public UpdateResult updateUserById(Long id, String userName, String note) {
        // 确定要更新的对象
        Criteria criteria = Criteria.where("id").is(id);
        Query query = Query.query(criteria);
        //定义更新对象
        Update update = Update.update("userName", userName);
        update.set("note", note);
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, User.class);
        // 更新多个文档
       // mongoTemplate.updateMulti(query, update, User.class);
        // 如果不存在文档，则新建文档，否则自更新文档
//        mongoTemplate.upsert(query, update, User.class);
        return updateResult;
    }
}
